/**
 * Фасад для jTweener. Предоставляет из себя более удобную и компактную 
 * структуру для создания анимации 
 * @author Sergey Chikuyonok (sc@design.ru)
 * @copyright Art.Lebedev Studio (http://www.artlebedev.ru)
 * @include "/jTweener/src/jTweener.js"
 * 
 * TODO добавить функцию rnd(min, max)
 */

(function(/* jTweener */ jTweener){
	// если фасад уже инициализирован, либо отсутствует jTweener — ничего не делаю
	if (window.$t || !jTweener)
		return;
	
	/**
	 * Проверяет, является ли переданный объект функцией
	 * @param {Object} obj
	 * @return {Boolean}
	 */
	function isFunction(obj){
		return (typeof obj == 'function');
	}
	
	/**
	 * Объединяет несколько объектов-хэшей в один
	 * @param {Object} ... Объекты, которые нужно объединить
	 * @return {Object}
	 */
	function merge(){
		return jTweener.Utils.mergeObjects.apply(this, arguments);
	}	
	
	/** Префикс для свойств процентных анимаций 
	 * (см. <code>jTweenerObj.prototype.percent</code>) 
	 */
	var prc_prefix = '__jto';
	
	/**
	 * Создает вспомогательный объект для создания анимаций через 
	 * <code>jTweener</code>. Этот объет удобен тем, что хранит в себе
	 * ссылки на анимируемые объекты, что сокращает объем кода, необходимый
	 * для работы с <code>jTweener</code>. В том числе удобен тем, что
	 * позволяет хранить и передавть несколько хэшей с параметрами анимаций,
	 * что позволяет, например, создать хэш со стандартными параметрами, которые
	 * будут применяться при анимации разных объектов.
	 * @return {jTweenerObj}
	 */
	var $t = function(obj, options){
		return new jTweenerObj(obj, Array.prototype.slice.call(arguments, 1));
	}
	
	/**
	 * Вспомогательный класс (фасад) для работы с jTweener
	 * @param {Element|Object|Array|jQuery} Объект или набор объектов, которые нужно анимировать
	 * @param {Object|Array} [options] Хэш (или массив хэшей) опций, которые будут применяться ко всем анимациям по умолчанию. Можно указать несколько аргументов с опициями
	 */
	function jTweenerObj(obj, options){
		this.obj = obj;
		this.options = {};
		if (options instanceof Array) {
			this.addOptions.apply(this, options);
		} else {
			this.addOptions(options);
		}
	}
	
	jTweenerObj.prototype = {
		/**
		 * Звпуск анимации. Принимает неограниченное количество аргументов,
		 * каждый из которых является набором параметров анимаций. Все эти опции
		 * (включая те, которые были указаны при создании объекта) объединяются
		 * в один набор в том порядке, в котором они были указаны.
		 * @param {Object} [options] Один или несколько наборов параметров анимации
		 * @return {jTweenerObj}
		 */
		tween: function(){
			var options;
			if (arguments.length) {
				options = Array.prototype.slice.call(arguments, 0);
				options.unshift(this.options);
				options = merge.apply(this, options);
			} else {
				options = this.options;
			}
			
			jTweener.addTween(this.obj, options);
			return this;
		},
		
		/**
		 * Создает особый вид анимации — процентную (см. <code>jTweener.addPercent</code>).
		 * От обычной она отличется тем, что все анимируемые свойства должны быть 
		 * функциями, принимающими один аргумент. Значение этого аргумента 
		 * изменяется от 0 до 1. Для удобства вместо хэшей с параметрами можно 
		 * отдавать функции
		 * @example
		 * var default_options = {time: 2, value: function(v){ console.log(v); }};<br>
		 * var obj = document.getElementById('test_obj');<br>
		 * $t(obj).percent(default_options, function(v){ console.log('same value is' + v); });
		 * @return {jTweenerObj}
		 */
		percent: function(){
			var args = [];
			// собираем все аргументы в один массив, чтобы из него создать один хэш
			for (var i = 0; i < arguments.length; i++) {
				if (isFunction(arguments[i])) {
					var obj = {};
					obj[prc_prefix + i] = arguments[i];
					args.push(obj);
				} else {
					args.push(arguments[i]);
				}
			}
			
			jTweener.addPercent(this.obj, merge.apply(this, args));
			return this;
		},
		
		/**
		 * Останавливает анимацию на всех объектах текущей выборки
		 * @return {jTweenerObj}
		 */
		stop: function(){
			jTweener.removeTween(this.obj);
			return this;
		},
		
		/**
		 * Добавляет параметры анимации к тем параметрам, которые будут 
		 * применятся по умолчанию при запуске любой анимации
		 * @param {Object} options Один или несколько хэшей с опциями
		 * @return {jTweenerObj}
		 */
		addOptions: function(){
			var opt = Array.prototype.slice.call(arguments, 0);
			opt.unshift(this.options);
			this.options = merge.apply(this, opt);
			return this;
		},
		
		/**
		 * Удаляет все параметры анимации, которые были установлены по умолчанию
		 * @return {jTweenerObj}
		 */
		clearOptions: function(){
			this.options = {};
			return this;
		},
		
		/**
		 * Удаляет указанные параметры из параметров анимации по умолчанию.
		 * Принимает неограниченное количество строковых параметров.
		 * @param {String} option Одно или несколько названий параметров, которые нужно удалить
		 * @return {jTweenerObj}
		 */
		removeOptions: function(){
			for (var i = 0; i < arguments.length; i++) {
				delete this.options[String(arguments[i])];
			}
			return this;
		}
	};
	
	// выношу наружу внутренние элементы
	window.$t = $t;
	
})(jTweener);